﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Dynamics.BusinessConnectorNet;
using System.Collections;

namespace PJ.Data
{
    /// <summary>
    /// Dynamics AX server implementation of <see cref="IEntityProvider"> persistence interface. 
    /// </summary>
    /// <typeparam name="TDataInterface">Entity data interface type</typeparam>
    /// <typeparam name="TDataConcreteClass">Entity data concrete class type</typeparam>
    public abstract class EntityAXProvider<TIEntityData> : ObjectAXProvider<TIEntityData>, IEntityProvider<TIEntityData>
        where TIEntityData : class, IEntityData
    {

        protected EntityAXProvider(IEntityCache<TIEntityData> cache) : base(cache)
        {
        }

        protected override void CopyFromContainer(IEnumerator enumerator, TIEntityData data)
        {
            base.CopyFromContainer(enumerator, data);
            if (enumerator.MoveNext())
                data.Id = ((string)enumerator.Current).Trim();
            else
                throw new ArgumentException("Container size error", "enumerator");
        }

        IEntityData IEntityProvider.GetById(string id, GetDataMode mode)
        {
            return GetById(id, mode);
        }


        public TIEntityData GetById(string id, GetDataMode mode)
        {
            if (id == null || id.Length == 0)
                throw new ArgumentNullException("id");
            TIEntityData data = null;
            if (Cache != null && (mode & GetDataMode.UseCache) == GetDataMode.UseCache)
                data = Cache.FindById(id);
            if (data == null)
            {
                using (AxaptaContainer container = (AxaptaContainer)CallAXStaticMethod("FindByID", id))
                {
                    IEnumerator enumerator = container.GetEnumerator();
                    if (enumerator.MoveNext())
                    {
                        data = CreateNewItem(enumerator);
                        if (enumerator.MoveNext())
                            throw new ArgumentException("Container size error", "container");
                        if (Cache != null)
                            Cache.Add(data);
                    }
                }
            }
            if (data == null && (mode & GetDataMode.Find) != GetDataMode.Find)
                throw new DataNotFoundException("id", id);
            return data;
        }

        private new IEntityCache<TIEntityData> Cache { get { return base.Cache as IEntityCache<TIEntityData>; } }
   }
}
